package com.uziot.bucket.common.concurrent.juc;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicReference;

/**
 * @author shidt
 * @version V1.0
 * @className AtomicReferenceTest
 * @date 2021-02-20 09:50:05
 * 演示引用类型的原子CAS操作
 * @description AtomicReference 提供了原子操作方法，通过两个参数的比较（预计值，更新值）
 * 当预计值为AtomicReference中保存的值为预计值时，执行更更新值的更新操作，并返回更新结果true、false
 * 当预计值和AtomicReference中保存的值不相同时，则不执行更新，返回false
 *
 * 此处 AtomicInteger ，一个提供原子操作的 Integer 的类，常见的还有
 * AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference 等，他们的实现原理相同，
 * 区别在与运算对象类型的不同。令人兴奋地，还可以通过 AtomicReference<V>将一个对象的所
 * 有操作转化成原子操作。
 * 我们知道，在多线程程序中，诸如++i 或 i++等运算不具有原子性，是不安全的线程操作之一。
 * 通常我们会使用 synchronized 将该操作变成一个原子操作，但 JVM 为此类操作特意提供了一些
 * 同步类，使得使用更方便，且使程序运行效率变得更高。通过相关资料显示，通常AtomicInteger
 * 的性能是 ReentantLock 的好几倍。
 */
@Slf4j
public class AtomicReferenceTest {
    public static void main(String[] args) {
        // 需要修改的实例对象
        String str1 = "我是字符串1";
        // 当前的实例对象
        AtomicReference<String> atomicStringReference = new AtomicReference<>(str1);
        // 设定修改之后的实例对象
        String str2 = "我是字符串2";

        log.info("str1===>{}", str1);
        log.info("str2===>{}", str2);
        log.info("======================");
        // 如果实例对象就是要修改的实例对象，则执行修改
        boolean b = atomicStringReference.compareAndSet(str1, str2);
        // 取得修改之后的对象
        String resultStr = atomicStringReference.get();
        log.info("str1===>{}", str1);
        log.info("str2===>{}", str2);
        log.info("change===>{},结果：{}", b, resultStr);

        log.info("======================");
        boolean b2 = atomicStringReference.compareAndSet(str1, str2);
        String resultStr2 = atomicStringReference.get();
        log.info("str1===>{}", str1);
        log.info("str2===>{}", str2);
        log.info("change===>{},结果：{}", b2, resultStr2);
    }
}
